package com.ljb.commlibrary.oss;

import android.app.Application;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider;
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask;
import com.alibaba.sdk.android.oss.model.OSSRequest;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.ljb.commlibrary.utils.StringUtils;


/**
 * Created by ljb on 2018/4/28.
 */

public class OssUtils {
    private static final String TAG = "OssUtils";
    private static OssUtils instance;
    private static OSSClient oss;
    private static boolean isDebug = true;

    private OssUtils() {
    }

    /**
     * 获取单例工具类
     *
     * @return 单例对象
     */
    public static OssUtils getInstance() {
        if (instance == null) {
            synchronized (OssUtils.class) {
                if (instance == null) {
                    instance = new OssUtils();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化OSS,在Application中进行初始化
     *
     * @param app             Application对象
     * @param accessKeyId
     * @param accessKeySecret
     * @param endpoint
     */
    public static void initOss(Application app, String accessKeyId, String accessKeySecret, String endpoint) {
        if (app == null || TextUtils.isEmpty(accessKeyId) || TextUtils.isEmpty(accessKeySecret) || TextUtils.isEmpty(endpoint)) {
            log("initOss: OSS初始化失败,相关参数为空");
            return;
        }
        OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(accessKeyId, accessKeySecret);
        oss = new OSSClient(app.getApplicationContext(), endpoint, credentialProvider);
        log("initOss: OSS初始化成功");
    }

    /**
     * 异步上传文件
     *
     * @param bucketName     bucket名称
     * @param objectKey      文件名称,如果想在OSS中显示层级结构,可以把objectKey写为"folder/subfolder/file"的格式,注意不能以'/'开头
     * @param uploadFilePath 文件上传路径
     * @return task异步任务, 可以调用task.cancel()取消任务, task.waitUntilFinished()等待直到任务完成
     */
    public OSSAsyncTask uploadObject(String bucketName, String objectKey, String uploadFilePath, final ProgressCallback<PutObjectRequest, PutObjectResult> callback) {
        if (oss == null) {
            log("uploadObject: OSS没有进行初始化");
            return null;
        }
        if (StringUtils.isEmpty(bucketName, objectKey, uploadFilePath)) {
            log("uploadObject 非法参数");
        }

        // 构造上传请求
        PutObjectRequest put = new PutObjectRequest(bucketName, objectKey, uploadFilePath);
        // 开启crc效验后。如果在传输中数据不一致，会直接抛出ClientException异常。
        // 提示InconsistentException: inconsistent object
        put.setCRC64(OSSRequest.CRC64Config.YES);
        //设置上传过程回调
        put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
            @Override
            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                if (callback != null)
                    callback.onProgress(request, currentSize, totalSize);
            }
        });

        //获取object文件上传后的路径
        final String objectURL = oss.presignPublicObjectURL(bucketName, objectKey);

        //开始上传
        return oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
            @Override
            public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                if (callback != null)
                    callback.onSuccess(request, result);
            }

            @Override
            public void onFailure(PutObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
                StringBuilder sb = new StringBuilder();
                // 本地异常
                if (clientExcepion != null) {
                    sb.append("客户端异常");
                    sb.append("\r\n");
                    sb.append("Message: ");
                    sb.append(clientExcepion.getMessage());
                    sb.append("\r\n");
                }
                //服务端异常
                if (serviceException != null) {
                    // 服务异常
                    sb.append("服务端异常");
                    sb.append("\r\n");
                    sb.append("RawMessage: ");
                    sb.append(serviceException.getRawMessage());
                    sb.append("\r\n");
                }
                log(sb.toString());
                if (callback != null)
                    callback.onFailure(request, clientExcepion, serviceException);
            }
        });
    }

    /**
     * 取消指定的task
     *
     * @param task 异步任务
     */
    public void cancel(OSSAsyncTask task) {
        if (task != null && !task.isCanceled()) {
            task.cancel();
        }
    }

    private static void log(String... content) {
        if (isDebug) {
            Log.e(TAG, TextUtils.join(",", content));
        }
    }
}
